// Effective C++ 条款26：尽可能延后变量定义式的出现时间
// 核心原则
// 尽量延后变量的定义，直到你确实需要它，并且在定义的同时进行初始化。

// 这个条款看似简单，但正确应用可以显著提高代码的效率和可读性。

// 为什么要延后变量定义
// 延后变量定义有几个重要优势：

// 1. 避免不必要的构造和析构成本 如果变量定义在函数开始处，但只在特定条件下使用，那么在不满足条件时，这个变量的构造和析构就是不必要的开销。
// 不好的做法
std::string encryptPassword(const std::string &password)
{
    std::string encrypted; // 过早定义，可能不会被使用

    if (password.length() < 8)
    {
        throw std::logic_error("Password too short");
        // encrypted被构造但从未使用，浪费资源
    }

    // 加密逻辑...
    encrypted = password; // 实际使用encrypted

    return encrypted;
}

// 更好的做法
std::string encryptPassword(const std::string &password)
{
    if (password.length() < 8)
    {
        throw std::logic_error("Password too short");
        // 没有不必要的变量构造
    }

    std::string encrypted = password; // 只在需要时定义并初始化
    // 加密逻辑...

    return encrypted;
}

// 2. 提高代码清晰度 变量的定义靠近其使用点，使代码更易于理解和维护。
// 不好的做法：变量定义与使用相距太远
void processData(const std::vector<int> &data)
{
    std::vector<int> filteredData; // 在这里定义
    double average;
    int sum = 0;

    // 大量其他代码...

    // 使用filteredData，可能与定义点相距很远
    for (int value : data)
    {
        if (value > 0)
        {
            filteredData.push_back(value);
        }
    }

    // 更多代码...

    // 使用sum和average
    for (int value : filteredData)
    {
        sum += value;
    }

    average = static_cast<double>(sum) / filteredData.size();
}

// 更好的做法：变量定义靠近使用点
void processData(const std::vector<int> &data)
{
    // 处理filteredData
    std::vector<int> filteredData; // 在使用前定义
    for (int value : data)
    {
        if (value > 0)
        {
            filteredData.push_back(value);
        }
    }

    // 计算平均值
    int sum = 0; // 在需要时定义
    for (int value : filteredData)
    {
        sum += value;
    }

    double average = static_cast<double>(sum) / filteredData.size(); // 在需要时定义
}

// 3. 减少作用域，避免未初始化变量
// 缩小变量的作用域可以减少错误，特别是使用未初始化变量的风险。
// 不好的做法：变量作用域过大
void processUserData()
{
    std::string name; // 作用域覆盖整个函数
    int age;

    // 大量代码...

    // 可能忘记初始化就使用
    std::cout << "Name: " << name << ", Age: " << age << std::endl; // 潜在的未定义行为
}

// 定义与初始化的最佳实践
// 1. 定义时进行初始化
// 总是在定义变量的同时进行初始化，避免默认构造后再赋值。
// 不好的做法：默认构造后赋值
std::string name;  // 调用默认构造函数
name = "John Doe"; // 调用赋值运算符

// 更好的做法：直接初始化
std::string name = "John Doe"; // 直接调用合适的构造函数
// 或者使用统一初始化语法（C++11及以后）
std::string name{"John Doe"};

// 2. 循环中的变量定义
// 对于循环中的变量，需要根据情况决定定义位置：

// 情况1：变量不依赖于循环
// 不好的做法：在循环内重复构造和析构
for (int i = 0; i < n; ++i)
{
    Widget w; // 每次迭代都构造和析构
    w.doSomething();
}

// 更好的做法：在循环外定义
Widget w; // 只构造一次
for (int i = 0; i < n; ++i)
{
    w.reset(); // 重置状态比完全重构造更高效
    w.doSomething();
} // 只析构一次

// 情况2：变量依赖于循环的当前迭代
// 正确的做法：在循环内定义
for (int i = 0; i < n; ++i)
{
    Widget w(i); // 使用循环变量初始化
    w.doSomething();
} // 每次迭代都需要不同的对象

// 实际例子
// 例子1：条件执行路径
// 不好的做法
bool processFile(const std::string &filename)
{
    std::ifstream dataFile(filename.c_str()); // 可能不需要

    if (!fileExists(filename))
    {
        return false; // dataFile被构造但从未使用
    }

    // 使用dataFile...
    return true;
}

// 更好的做法
bool processFile(const std::string &filename)
{
    if (!fileExists(filename))
    {
        return false; // 没有不必要的构造
    }

    std::ifstream dataFile(filename.c_str()); // 只在需要时构造
    // 使用dataFile...
    return true;
}

// 例子2：异常安全
// 延后变量定义也有助于提高异常安全性：
// 不好的做法：可能导致资源泄漏
void riskyFunction()
{
    Resource *res = new Resource(); // 分配资源

    // 如果下面的操作抛出异常，res将泄漏
    performOperation(); // 可能抛出异常

    delete res; // 可能永远不会执行
}

// 更好的做法：使用RAII和延后定义
void saferFunction()
{
    performOperation(); // 如果这里抛出异常，没有资源需要清理

    std::unique_ptr<Resource> res(new Resource()); // 只在需要时分配，并使用智能指针管理
    // 使用res...
} // res自动清理

// 性能考虑
// 延后变量定义通常会提高性能，但也有例外情况：
// 情况：函数可能提前返回，但变量构造成本很低
bool containsNegative(const std::vector<int> &values)
{
    // 方法1：延后定义
    for (size_t i = 0; i < values.size(); ++i)
    {
        if (values[i] < 0)
        {
            return true; // 提前返回
        }
    }

    std::string message = "No negative values found"; // 只在需要时构造
    log(message);
    return false;

    // 方法2：提前定义（在某些情况下可能更高效）
    std::string message; // 默认构造成本很低

    for (size_t i = 0; i < values.size(); ++i)
    {
        if (values[i] < 0)
        {
            message = "Found negative value";
            log(message);
            return true;
        }
    }

    message = "No negative values found";
    log(message);
    return false;
}
// 在这个例子中，如果默认构造和赋值的总成本低于条件构造的成本，方法2可能更高效。但通常情况下，方法1更清晰且通常更高效。

// 总结
// 条款26的核心建议是：

// 尽量延后变量定义，直到真正需要它
// 定义时进行初始化，避免默认构造后再赋值
// 考虑循环中变量的最佳定义位置，取决于变量是否依赖于循环的当前迭代
// 权衡清晰性和效率，通常延后定义既提高清晰性又提高效率
// 遵循这个条款可以帮助你编写更高效、更清晰、更不易出错的代码。